#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "iot_gpio_ex.h"
#include "medical_kit.h"
#include "uart.h"
#include "KitWS2812.h"

#include <hi_uart.h>
#include "uart.h"
#include <iot_uart.h>
#include <hi_gpio.h>
#include <hi_io.h>
#include <hi_flash_base.h>

#include <hi_mux.h>
#include <hi_wifi_api.h>
#include "iot_config.h"
#include "iot_log.h"
#include "iot_main.h"
#include "iot_profile.h"

#define LED_INTERVAL_TIME_US 300000
#define LED_TASK_STACK_SIZE 512
#define LED_TASK_PRIO 25
#define LED_TEST_GPIO 9 // for hispark_pegasus

#define KIT_FLASH_DRUG_OFFSET   0x1FA000
#define KIT_FLASH_USER_OFFSET   0x1FF000
#define KIT_FLASH_SIZE     1024

#define KIT_FLASH_INIT_OFFSET 0x1FD000

/**********************************/

/* attribute initiative to report */
#define TAKE_THE_INITIATIVE_TO_REPORT
#define ONE_SECOND                          (1000)
/* oc request id */
#define CN_COMMADN_INDEX                    "commands/request_id="
#define WECHAT_SUBSCRIBE_LIGHT              "light"
#define WECHAT_SUBSCRIBE_NOWTIME            "appTime"           //获取网络时间
#define WECHAT_SUBSCRIBE_LIGHT_ON_STATE     "1"
#define WECHAT_SUBSCRIBE_LIGHT_OFF_STATE    "0"

int g_ligthStatus = -1;
typedef void (*FnMsgCallBack)(hi_gpio_value val);

typedef struct FunctionCallback {
    hi_bool  stop;
    hi_u32 conLost;
    hi_u32 queueID;
    hi_u32 iotTaskID;
    FnMsgCallBack    msgCallBack;
}FunctionCallback;
FunctionCallback g_functionCallback;
/************************************/

int PositionNow = 1;
int dis = 0;
int FindOrginFlag = 0;
hi_u8 voiceDat = 0;
hi_s8 faceDat = 0;
static int voicState = 0;
extern int first_wakeup_flag;

static PeopleInf UserData[Users_Num_MAX];
static DrugInf   DrugData[Drug_Num_MAX];
static LogInf    UserLog[Users_Num_MAX];
static hi_u8 Kit_Write_Flash_BUF[256];
static hi_u8 Kit_Read_Flash_BUF[256];
static hi_u8 Kit_Read_Flash_INIT_BUF[4];
static hi_u8 ntime,time;
static TimeInf nowtime;
//hi_u8 nHH=9,nMM=0;

void KitRotate(int val)
{   
    if(val==1)
    {
        IoTGpioSetOutputVal(MOTOR1_GPIO_OUT,0);
        IoTGpioSetOutputVal(MOTOR2_GPIO_OUT,1);
    }
    else if(val ==2)
    {
        IoTGpioSetOutputVal(MOTOR1_GPIO_OUT,1);
        IoTGpioSetOutputVal(MOTOR2_GPIO_OUT,0);
    }
    else
    {
        IoTGpioSetOutputVal(MOTOR1_GPIO_OUT,0);
        IoTGpioSetOutputVal(MOTOR2_GPIO_OUT,0);
    }
}
int count_flag=0;
char door_state = 0;         
void KitState(char *state)
{   
    int ret;
    int open_val = 0,close_val = 0;
    IoTGpioGetInputVal(DOOR_OPEN_GPIO_IN, &open_val);
    usleep(100000);
    ret=IoTGpioGetInputVal(DOOR_CLOSE_GPIO_IN, &close_val);
    printf("ret = %d,last state = %d\n",ret,*state);
    usleep(100000);
    if(open_val == 1 && close_val == 0 && *state!=3 && *state!=4 && *state!=5 && *state!=6)         //close
        *state = 1;
    else if(open_val == 0 && close_val == 1 && *state!=3 && *state!=4 && *state!=5 && *state!=6)    //open
        *state = 2;
    else if(open_val == 1 && close_val == 1)                //taking
        *state = 3;
    else if(open_val == 0 && close_val == 1 && *state==3)    //end
        *state = 4;
    else if(*state==4)    //end
    {   
        KitRotate(1);
        usleep(100000);
        KitRotate(0);
        while(1)
        {
            usleep(300000);
            ret=IoTGpioGetInputVal(DOOR_CLOSE_GPIO_IN, &close_val);
            usleep(100000);
            printf("ret == %d close_val =%d\n",ret,close_val);
            if(ret==0)
                break;
        }
        if(close_val != 0)
        {   
            KitRotate(2);
            usleep(200000);
            KitRotate(0);
            *state = 3;
        }
        else 
        {   
           *state = 1;
        }
        
    }
    printf("open_val = %d ,close_val = %d,state = %d\n",open_val,close_val,*state);
}
void KitInit(void)
{
    hi_u32 ret;
    //init GPIO
    IoTGpioInit(MOTOR1_GPIO_OUT);
    IoTGpioInit(MOTOR2_GPIO_OUT);
    IoTGpioInit(IR1_GPIO_IN);
    IoTGpioInit(IR2_GPIO_IN);
    IoTGpioInit(LED_TEST_GPIO);
    IoTGpioInit(DOOR_OPEN_GPIO_IN);
    IoTGpioInit(DOOR_CLOSE_GPIO_IN);

    //Set Default Output Val
    IoTGpioSetOutputVal(MOTOR1_GPIO_OUT,0);
    IoTGpioSetOutputVal(MOTOR2_GPIO_OUT,0);

    //Set Func
    IoSetFunc(MOTOR1_GPIO_OUT, IOT_IO_FUNC_GPIO_2_GPIO);
    IoSetFunc(MOTOR2_GPIO_OUT, IOT_IO_FUNC_GPIO_8_GPIO);
    IoSetFunc(IR1_GPIO_IN, IOT_IO_FUNC_GPIO_7_GPIO);
    IoSetFunc(IR2_GPIO_IN, IOT_IO_FUNC_GPIO_10_GPIO);
    IoSetFunc(DOOR_OPEN_GPIO_IN, IOT_IO_FUNC_GPIO_13_GPIO);
    IoSetFunc(DOOR_CLOSE_GPIO_IN, IOT_IO_FUNC_GPIO_14_GPIO);

    //Set Dir
    IoTGpioSetDir(MOTOR1_GPIO_OUT, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(MOTOR2_GPIO_OUT, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(IR1_GPIO_IN, IOT_GPIO_DIR_IN);
    IoTGpioSetDir(IR2_GPIO_IN, IOT_GPIO_DIR_IN);
    IoTGpioSetDir(LED_TEST_GPIO, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(DOOR_OPEN_GPIO_IN, IOT_GPIO_DIR_IN);
    IoTGpioSetDir(DOOR_CLOSE_GPIO_IN, IOT_GPIO_DIR_IN);

    //Set Pull
    IoSetPull(IR1_GPIO_IN, 1);  
    IoSetPull(IR2_GPIO_IN, 2);  
    IoSetPull(DOOR_OPEN_GPIO_IN, 1); 
    IoSetPull(DOOR_CLOSE_GPIO_IN, 1);  

    UartInit();
    Kit_LED_init();
    nowtime.year = 2022;
    nowtime.month = 7;
    nowtime.day = 6;
    nowtime.Hour = 9;
    nowtime.Min = 0;
    voicState = LED_EXIT;
}

void KitFindOrigin(void)
{
    IotGpioValue val = 1;
    FindOrginFlag=1;
    KitRotate(1);
    while(1)
    {
        IoTGpioGetInputVal(IR1_GPIO_IN, &val);
        usleep(100000);
        if(!val)
         {  
             KitRotate(0);
             break;
         }       
    } 
    PositionNow = 1;
    FindOrginFlag=0;
}

void KitOpen()
{
    KitRotate(1);
    usleep(400000);
    KitRotate(2);
    usleep(400000);
    KitRotate(0);       
}
void KitShut()
{
    KitRotate(1);
    usleep(300000);
    KitRotate(2);
    usleep(300000);
    KitRotate(0);       
}
void KitLocate(int num,int open)
{
    IotGpioValue val = 0;
    KitRotate(1);
    if(num > PositionNow)
        dis = num - PositionNow;
    else
    {
        dis = 10 - PositionNow + num;
    }
    PositionNow = num;

    while (1)
    {

        if(dis<=0)
        {
             if(num == 1)
            {
                usleep(400000);
            }
            else if(num == 2)
            {
                usleep(400000);
            }
            else if(num == 3)
            {
                usleep(300000);
            }
            else if(num ==10)
            {
                usleep(320000);
            }
            KitRotate(0);
            break;
        }
        IoTGpioGetInputVal(IR2_GPIO_IN, &val);
        usleep(10000);
        if(val)     //if high
        {
            while (1)    //wait low
            {   
                val=1;
                IoTGpioGetInputVal(IR2_GPIO_IN, &val);
                usleep(10000);
                if(val==0)  //if low
                {   
                    dis--;     
                    break;
                }

            }
            printf("dis = %d\n",dis);    
        }
    }
    if(open == 1)
    {
        KitOpen();
    }
           
}

void KitWriteUserDataBase(void)
{   
    hi_u32 ret;
    memset_s(Kit_Write_Flash_BUF, sizeof(Kit_Write_Flash_BUF), 0, sizeof(Kit_Write_Flash_BUF));
    for(int i=0;i<Users_Num_MAX;i++)
    {
        Kit_Write_Flash_BUF[0] = UserData[i].ID;
        Kit_Write_Flash_BUF[1] = UserData[i].Fill;
        if(Kit_Write_Flash_BUF[1] == 1)
        {
            Kit_Write_Flash_BUF[2] = UserData[i].NameLen;         
            for(int j=0;j < UserData[i].NameLen; j++)            //写入人名
            {
                Kit_Write_Flash_BUF[3+j] = UserData[i].Name[j];      
            }
            Kit_Write_Flash_BUF[3 + UserData[i].NameLen] = UserData[i].DrugNum;  //写入对应人需要药物种类数
            for(int k=0;k < UserData[i].DrugNum; k++)            //写入服用药的信息
            {
                Kit_Write_Flash_BUF[3 + UserData[i].NameLen + 1 + k ] = UserData[i].DrugID[k];
                Kit_Write_Flash_BUF[3 + UserData[i].NameLen + 1 + k + 1 ] = UserData[i].Times[k];
                for(int l=0;l < UserData[i].Times[k];l++)
                {
                    Kit_Write_Flash_BUF[3 + UserData[i].NameLen + 1 + k + 2 + l] = UserData[i].DosageTime[k][l];
                }
                Kit_Write_Flash_BUF[3 + UserData[i].NameLen + 1 + k + 2 + UserData[i].Times[k]] = UserData[i].TimeOut[k];
            }
            ret = hi_flash_write(KIT_FLASH_USER_OFFSET  + (i * sizeof(Kit_Write_Flash_BUF)), sizeof(Kit_Write_Flash_BUF), Kit_Write_Flash_BUF, HI_TRUE);
            if (ret != HI_ERR_SUCCESS) {
                printf("write fail:%x\n", ret);
                }
        }
    }    
}
void KitWriteDrugDataBase(void)
{   
    hi_u32 ret;
    memset_s(Kit_Write_Flash_BUF, sizeof(Kit_Write_Flash_BUF), 0, sizeof(Kit_Write_Flash_BUF));
    for(int i=0;i<Drug_Num_MAX;i++)
    {
        Kit_Write_Flash_BUF[0] = DrugData[i].ID;
        Kit_Write_Flash_BUF[1] = DrugData[i].Fill;
        if(Kit_Write_Flash_BUF[1] == 1)
        {
            Kit_Write_Flash_BUF[2] = DrugData[i].NameLen;         
            for(int j=0;j < DrugData[i].NameLen; j++)            //写入药名
            {
                Kit_Write_Flash_BUF[3+j] = DrugData[i].Name[j];      
            }
            Kit_Write_Flash_BUF[3 + DrugData[i].NameLen] = DrugData[i].DrugTotal;  //写入药物总量
            Kit_Write_Flash_BUF[4 + DrugData[i].NameLen] = DrugData[i].Location;   //写入药物存放位置
            ret = hi_flash_write(KIT_FLASH_DRUG_OFFSET  + (i * sizeof(Kit_Write_Flash_BUF)), sizeof(Kit_Write_Flash_BUF), Kit_Write_Flash_BUF, HI_TRUE);
            if (ret != HI_ERR_SUCCESS) {
                printf("write fail:%x\n", ret);
                }
        }
    }    
}
void KitReadUserDataBase(void)
{   
    hi_u32 ret;
    memset_s(Kit_Read_Flash_BUF, sizeof(Kit_Read_Flash_BUF), 0, sizeof(Kit_Read_Flash_BUF));
    for(int i=0;i<Users_Num_MAX;i++)
    {  
        ret = hi_flash_read(KIT_FLASH_USER_OFFSET + (i * sizeof(Kit_Read_Flash_BUF)), sizeof(Kit_Read_Flash_BUF), Kit_Read_Flash_BUF);
        if (ret != HI_ERR_SUCCESS) {
            printf("I= %dread fail:%x\n", i,ret);
        }
        UserData[i].ID = Kit_Read_Flash_BUF[0];
        UserData[i].Fill = Kit_Read_Flash_BUF[1];
        if(Kit_Read_Flash_BUF[1] == 1)
        {
            UserData[i].NameLen = Kit_Read_Flash_BUF[2];     
            for(int j=0;j < UserData[i].NameLen; j++)            //读取人名
            {
                UserData[i].Name[j] = Kit_Read_Flash_BUF[3+j];      
            }
            UserData[i].DrugNum = Kit_Read_Flash_BUF[3 + UserData[i].NameLen];  //读取对应人需要药物种类数
            
            for(int k=0;k < UserData[i].DrugNum; k++)            //读取服用药的信息
            {
                UserData[i].DrugID[k] = Kit_Read_Flash_BUF[3 + UserData[i].NameLen + 1 + k ];
                UserData[i].Times[k] = Kit_Read_Flash_BUF[3 + UserData[i].NameLen + 1 + k + 1];
                for(int l=0;l < UserData[i].Times[k];l++)
                {
                    UserData[i].DosageTime[k][l] = Kit_Read_Flash_BUF[3 + UserData[i].NameLen + 1 + k + 2 + l];
                }
                UserData[i].TimeOut[k] = Kit_Read_Flash_BUF[3 + UserData[i].NameLen + 1 + k + 2 + UserData[i].Times[k]];
            }
        }
    }    
}
void KitReadDrugDataBase(void)
{   
    hi_u32 ret;
    memset_s(Kit_Read_Flash_BUF, sizeof(Kit_Read_Flash_BUF), 0, sizeof(Kit_Read_Flash_BUF));
    for(int i=0;i<Drug_Num_MAX;i++)
    {  
        ret = hi_flash_read(KIT_FLASH_DRUG_OFFSET + (i * sizeof(Kit_Read_Flash_BUF)), sizeof(Kit_Read_Flash_BUF), Kit_Read_Flash_BUF);
        if (ret != HI_ERR_SUCCESS) {
            printf("I= %dread fail:%x\n", i,ret);
        }
        DrugData[i].ID = Kit_Read_Flash_BUF[0];
        DrugData[i].Fill = Kit_Read_Flash_BUF[1];
        if(Kit_Read_Flash_BUF[1] == 1)
        {
            DrugData[i].NameLen = Kit_Read_Flash_BUF[2];     
            for(int j=0;j < DrugData[i].NameLen; j++)            //读取药名
            {
                DrugData[i].Name[j] = Kit_Read_Flash_BUF[3+j];      
            }
            DrugData[i].DrugTotal = Kit_Read_Flash_BUF[3 + DrugData[i].NameLen];  //读取药物总量4
            DrugData[i].Location  = Kit_Read_Flash_BUF[4 + DrugData[i].NameLen] ;   //读取药物存放位置
        }
    }    
}
void KitReadVoiceData(hi_u8 *data)
{   
    int len = 0;
    hi_u8 uartBuff[UART_BUFF_SIZE] = {0};
    memset(uartBuff, 0, sizeof(uartBuff));
     // 通过串口2接收数据
    len = IoTUartRead(HI_UART_IDX_2, uartBuff, VOICE_DATA_LEN);         //语音帧头，帧尾，简单校验 aa 66 voice result 66 aa
    if ((len > 0) && (uartBuff[0] == 0xaa) && (uartBuff[1] == 0x66) && (uartBuff[3] == 0x66) && (uartBuff[4] == 0xaa)) {
        printf("voice data:%x %x %x %x %x  \n",uartBuff[0],uartBuff[1],uartBuff[2],uartBuff[3],uartBuff[0],uartBuff[4]);
        *data = uartBuff[2];
    }
    else
        *data = 0;
}
void KitReadDetectData(hi_s8 *data)
{   
    int len = 0;
    hi_u8 uartBuff[UART_BUFF_SIZE] = {0};
    memset(uartBuff, 0, sizeof(uartBuff));
     // 通过串口1接收数据
    len = IoTUartRead(HI_UART_IDX_1, uartBuff, VOICE_DATA_LEN);          //人脸识别帧头，帧尾，简单校验 aa cc detect result cc aa
    if ((len > 0) && (uartBuff[0] == 0xaa) && (uartBuff[1] == 0xcc) && (uartBuff[3] == 0xcc) && (uartBuff[4] == 0xaa)) {
        printf("Detect data:%x %x %x %x %x  \n",uartBuff[0],uartBuff[1],uartBuff[2],uartBuff[3],uartBuff[4]);
        *data = uartBuff[2];
    }
    else
        *data = 99;
}
hi_u8 KitPickUp(void)
{
    //hi_u8 faceDat;
    hi_u8 nHH=9,nMM=0;          //演示以9点为例
    hi_u8 uartBuff[UART_BUFF_SIZE] = {0};
    hi_u8 userPlace,drugPlace;
    memset(uartBuff, 0, sizeof(uartBuff));
    sleep(3);
    printf("faceDat = %d\n",faceDat);
    if(faceDat == 99)                        //检测不到人脸
    {
        uartBuff[0]=0xAA;
        uartBuff[1]=0x55;
        uartBuff[2]=0x01;
        uartBuff[3]=0x00;
        uartBuff[4]=0x55;
        uartBuff[5]=0xAA;
        IoTUartWrite(HI_UART_IDX_2,uartBuff,6);     //语音内容：我看不到你，请您站在镜头前
        sleep(8);
        printf("faceDat = %d\n",faceDat);      //再次检测
    }
    
    if(faceDat != 99)                        //检测到人脸
    {   
        for(int i=0;i<10;i++)
       {
           if(UserData[i].ID == faceDat)     //找出对应ID存储的位置num
           {
               userPlace = i;
           }
       }

        if(UserData[userPlace].DrugNum>0)      //判断服药种类是否大于0
        {   
            uartBuff[0]=0xAA;
            uartBuff[1]=0x55;
            uartBuff[2]=0x02;
            uartBuff[3]=UserData[userPlace].ID;
            uartBuff[4]=UserData[userPlace].DrugNum;
            uartBuff[5]=0x55;
            uartBuff[6]=0xAA;
            IoTUartWrite(HI_UART_IDX_2,uartBuff,7);     //语音内容：用户$UserlD您好呀，今天需要服用$DrugNum种药，分别是
            sleep(7);
            for(int i=0;i<UserData[userPlace].DrugNum;i++)         //查阅用户需要服药类型数量
            {
               if(UserLog[userPlace].Num[i] >= UserData[userPlace].Times[i]) 
                {    
                    if( UserLog[userPlace].FinishState[i] != 1)
                    {
                        UserLog[userPlace].FinishNum++;                //统计药物种类服用完成数量
                        UserLog[userPlace].FinishState[i] = 1;         //今天已经服用完某一种药的指定次数
                    }
                    // uartBuff[0]=0xAA;
                    // uartBuff[1]=0x55;
                    // uartBuff[2]=0x01;
                    // uartBuff[3]=0x00;
                    // uartBuff[4]=0x55;
                    // uartBuff[5]=0xAA;
                    // IoTUartWrite(HI_UART_IDX_2,uartBuff,6);  //语音内容：你今天已经服用完药物ID号药啦
                }
                else                                            //检查哪种药还没服完
                {
                    UserLog[userPlace].FinishState[i] = 2;         //今天某一种药还未完成
                    UserLog[userPlace].UnFinishNum++;              //统计药物种类未服用完成数量
                    //获取当前时间
                    ntime = nowtime.Hour * 60 + nowtime.Min  ;       //转化为分钟
                    
                    for(int j=0;j<UserData[userPlace].Times[i];j++)
                    {
                        //判断是否到达服药时间
                        time = UserData[userPlace].DosageTime[i][j] * 60;  
                        if(ntime >= time && ntime <= (time + 60))       //到达服药时间
                        {
                            for(int k=0;k<10;k++)
                            {
                                if(DrugData[k].ID == UserData[userPlace].DrugID[i])     //找出对应药物ID存储的位置drugPlace
                                {
                                    drugPlace = k;
                                }
                            }
                            UserLog[userPlace].Num[i]++;                   //用药次数+1
                            UserLog[userPlace].Hour = nowtime.Hour;        //记录取药时间
                            UserLog[userPlace].Min = nowtime.Min;
                            uartBuff[0]=0xAA;
                            uartBuff[1]=0x55;
                            uartBuff[2]=0x03;
                            uartBuff[3]=UserData[userPlace].DrugID[i];
                            uartBuff[4]=UserData[userPlace].Times[i];      
                            uartBuff[5]=UserLog[userPlace].Num[i];  
                            uartBuff[6]=DrugData[drugPlace].Location;  
                            uartBuff[7]=0x55;             
                            uartBuff[8]=0xAA;
                            IoTUartWrite(HI_UART_IDX_2,uartBuff,9);              //语音内容：$DruglD号药，今天需要服用$Times次，这是第$Num次啦,药物放在第$Place号仓
                            KitLocate(DrugData[drugPlace].Location,1);   //打开药盒
                            DrugData[drugPlace].DrugTotal--;       //药物数量-1
                            //KitWriteDrugDataBase();                 //写入Flash
                            while (1)
                            {
                                sleep(1);
                                KitState(&door_state); 
                                if(door_state == 1)
                                    break;
                            }  
                        }
                        else
                        {
                            // uartBuff[0]=0xAA;
                            // uartBuff[1]=0x55;
                            // uartBuff[2]=0x05;
                            // uartBuff[3]=UserData[userPlace].ID;
                            // uartBuff[4]=0x55;             
                            // uartBuff[5]=0xAA;
                            // IoTUartWrite(HI_UART_IDX_2,uartBuff,6);             //语音内容：用户$ID,您好。您还未到指定服药时间。
                        }
                    }
                   
                }
               
            }
            if(UserLog[userPlace].FinishNum == UserData[userPlace].DrugNum)   //当服用的所有药与设定一样 即当天已经服完药了
            {
                uartBuff[0]=0xAA;
                uartBuff[1]=0x55;
                uartBuff[2]=0x04;
                uartBuff[3]=UserData[userPlace].ID;
                uartBuff[4]=0x55;
                uartBuff[5]=0xAA;
                usleep(3000000);
                IoTUartWrite(HI_UART_IDX_2,uartBuff,6);         //语音内容：用户ID棒棒哒，你今天已经服完所有药了
            }
        }
        else
        {
            uartBuff[0]=0xAA;
            uartBuff[1]=0x55;
            uartBuff[2]=0x06;
            uartBuff[3]=UserData[userPlace].ID;
            uartBuff[4]=0x55;
            uartBuff[5]=0xAA;
            IoTUartWrite(HI_UART_IDX_2,uartBuff,6);     //语音内容：用户ID您好查不到您需要服用的药，您可以到小程序添加服药计划
        }
    }
}
static void *KitTask(const char *arg)
{
    (void)arg;
    unsigned char uartBuff[11] = {0};
    hi_u32 ret;

    ret = hi_flash_init();
    if (ret == HI_ERR_FLASH_RE_INIT) {
        printf("Flash has already been initialized!\n");
    } else if (ret != HI_ERR_SUCCESS) {
        printf("Falied to init flash, err = %X\n", ret);
    }
    KitReadUserDataBase();
     //打印测试，可去除
    printf("%d %d %d %s NUM:%d ID:%d T:%d %d %d %d TO:%d ID:%d T:%d %d %d TO:%d \n",UserData[0].ID,UserData[0].Fill,UserData[0].NameLen,
    UserData[0].Name,UserData[0].DrugNum,UserData[0].DrugID[0],UserData[0].Times[0],UserData[0].DosageTime[0][0],UserData[0].DosageTime[0][1],
    UserData[0].DosageTime[0][2],UserData[0].TimeOut[0],UserData[0].DrugID[1],UserData[0].Times[1],UserData[0].DosageTime[1][0],UserData[0].DosageTime[1][1],
    UserData[0].TimeOut[1]);

    printf("%d %d %d %s NUM:%d ID:%d T:%d %d %d %d TO:%d\n",UserData[1].ID,UserData[1].Fill,UserData[1].NameLen,
    UserData[1].Name,UserData[1].DrugNum,UserData[1].DrugID[0],UserData[1].Times[0],UserData[1].DosageTime[0][0],UserData[1].DosageTime[0][1],
    UserData[1].DosageTime[0][2],UserData[1].TimeOut[0]);

    KitReadDrugDataBase();          
    //打印测试，可去除
    printf("id:%d fill:%d namelen:%d name:%s total:%d loc:%d \n",DrugData[0].ID,DrugData[0].Fill,DrugData[0].NameLen,DrugData[0].Name,DrugData[0].DrugTotal,DrugData[0].Location);
    printf("id:%d fill:%d namelen:%d name:%s total:%d loc:%d \n",DrugData[1].ID,DrugData[1].Fill,DrugData[1].NameLen,DrugData[1].Name,DrugData[1].DrugTotal,DrugData[1].Location);
    printf("id:%d fill:%d namelen:%d name:%s total:%d loc:%d \n",DrugData[2].ID,DrugData[2].Fill,DrugData[2].NameLen,DrugData[2].Name,DrugData[2].DrugTotal,DrugData[2].Location);
    ret = hi_flash_read(KIT_FLASH_INIT_OFFSET, sizeof(Kit_Read_Flash_INIT_BUF), Kit_Read_Flash_INIT_BUF);
    if (ret != HI_ERR_SUCCESS) {
        return;
    }
    if(Kit_Read_Flash_INIT_BUF[0]!=0x66 && Kit_Read_Flash_INIT_BUF[1]!=0x66)    //第一次使用，FLASH无数据，载入默认数据测试，以下为默认测试
    {
        printf("First time using the kit\n");               
        /*********** test  **************************/
        UserData[0].ID = 1;                    //People ID
        strcpy(UserData[0].Name,"Liudehua");   //Name
        UserData[0].NameLen = 8;               //Length of name
        UserData[0].Fill = 1;                 //Enabled or not               
        UserData[0].DrugNum = 2;               //Number of medication types taken
        UserData[0].DrugID[0] = 1;            //Drug ID
        UserData[0].DrugID[1] = 2;            //Drug ID
        UserData[0].Times[0]  = 3;             //Number of doses per day
        UserData[0].Times[1]  = 2;             //Number of doses per day
        UserData[0].TimeOut[0] = 60;           //Alarm time(min)
        UserData[0].TimeOut[1] = 40;           //Alarm time(min)
        UserData[0].DosageTime[0][0] = 9;        //Drug ID:Dosing time(0~23h)
        UserData[0].DosageTime[0][1] = 12;
        UserData[0].DosageTime[0][2] = 16;
        UserData[0].DosageTime[1][0] = 9;        //Drug ID:Dosing time(0~23h)
        UserData[0].DosageTime[1][1] = 18;

        UserData[1].ID = 2;                    //People ID
        strcpy(UserData[1].Name,"Zhoujielun");   //Name
        UserData[1].NameLen = 10;               //Length of name
        UserData[1].Fill = 1;                 //Enabled or not               
        UserData[1].DrugNum = 0;               //Number of medication types taken
        UserData[1].DrugID[0] = 2;            //Drug ID
        UserData[1].Times[0]  = 3;             //Number of doses per day
        UserData[1].TimeOut[0] = 60;           //Alarm time(min)
        UserData[1].DosageTime[0][0] = 9;        //Drug ID:Dosing time(0~23h)
        UserData[1].DosageTime[0][1] = 14;
        UserData[1].DosageTime[0][2] = 19;

        UserData[2].ID = 3;                    //People ID
        strcpy(UserData[2].Name,"Gaotianyu");             //Name
        UserData[2].NameLen = 9;               //Length of name
        UserData[2].Fill = 1;                 //Enabled or not               
        UserData[2].DrugNum = 2;               //Number of medication types taken
        UserData[2].DrugID[0] = 1;            //Drug ID
        UserData[2].DrugID[1] = 3;            //Drug ID
        UserData[2].Times[0]  = 3;             //Number of doses per day
        UserData[2].Times[1]  = 2;             //Number of doses per day
        UserData[2].TimeOut[0] = 60;           //Alarm time(min)
        UserData[2].TimeOut[1] = 40;           //Alarm time(min)
        UserData[2].DosageTime[0][0] = 9;        //Drug ID:Dosing time(0~23h)
        UserData[2].DosageTime[0][1] = 12;
        UserData[2].DosageTime[0][2] = 16;
        UserData[2].DosageTime[1][0] = 9;        //Drug ID:Dosing time(0~23h)
        UserData[2].DosageTime[1][1] = 18;
        KitWriteUserDataBase();
        usleep(10000);

        DrugData[0].ID = 1;      
        strcpy(DrugData[0].Name,"999ganmaoling");   //Name                      
        DrugData[0].NameLen = 13;             
        DrugData[0].Fill = 1;                    
        DrugData[0].DrugTotal = 100;           
        DrugData[0].Location = 1;

        DrugData[1].ID = 2;                 
        strcpy(DrugData[1].Name,"VC");   //Name           
        DrugData[1].NameLen = 2;             
        DrugData[1].Fill = 1;                    
        DrugData[1].DrugTotal = 88;           
        DrugData[1].Location = 6;

        DrugData[2].ID = 3;                 
        strcpy(DrugData[2].Name,"CalciumTablets");   //Name          
        DrugData[2].NameLen = 4;             
        DrugData[2].Fill = 1;                    
        DrugData[2].DrugTotal = 52;           
        DrugData[2].Location = 3;
        KitWriteDrugDataBase();
        usleep(10000);

        Kit_Read_Flash_INIT_BUF[0]=0x66;                    //清楚第一次载入标志，下次启动数据库来源于FLASH
        Kit_Read_Flash_INIT_BUF[1]=0x66;
        ret = hi_flash_write(KIT_FLASH_INIT_OFFSET, sizeof(Kit_Read_Flash_INIT_BUF), Kit_Read_Flash_INIT_BUF, HI_TRUE);
        if (ret != HI_ERR_SUCCESS) {
            printf("write fail:%x\n", ret);
            }
    }
        /*********** test  **************************/
    KitFindOrigin();           //定位药盒

    while (1)
    {  
        KitState(&door_state);
        printf("voicState = %d\n",voicState); 
        if(door_state == 1)
        {
            switch(voiceDat)
            {
                case 1:
                    KitLocate(1,1);         //定位开锁，语音消息：打开一号（药箱/药盒）
                    break;
                case 2:
                    KitLocate(2,1); 
                    break;
                case 3:
                    KitLocate(3,1);
                    break;
                case 4:
                    KitLocate(4,1);  
                    break;
                case 5:
                    KitLocate(5,1);
                    break;
                case 6:
                    KitLocate(6,1);  
                    break;
                case 7:
                    KitLocate(7,1); 
                    break;
                case 8:
                    KitLocate(8,1); 
                    break;
                case 9:
                    KitLocate(9,1);   
                    break;        
                case 10:
                    KitLocate(10,1);      
                    break;  
                case 0x99:      //取药命令
                    KitPickUp();
                    break; 
                default:
                    break;                  
            }
            voiceDat = 0;
        }
        sleep(1);
    }

    return NULL;
}

int Last_IS_BREATH_FLAG = 0;
static int VoiceTask(void)
{
    while (1) {
        KitReadVoiceData(&voiceDat);
        switch(voiceDat)
        {   
            case 0x88:
                if(voicState == LED_BREATH)
                    Last_IS_BREATH_FLAG=1;
                voicState = LED_WAKE_UP;
                first_wakeup_flag = 0;
                break; 
            case 0x66:
                voicState = LED_BREATH;
                break; 
            case 0x67:
                voicState = LED_EXIT;
                Last_IS_BREATH_FLAG=0;
                break; 
            case 0x77:
                if(voicState != LED_BREATH)
                {   
                    if(!Last_IS_BREATH_FLAG)
                        voicState = LED_EXIT;
                    else
                    {    voicState = LED_BREATH;
                         Last_IS_BREATH_FLAG=0;
                    }
                }
            default:
                break;                  
        }
        sleep(3);
    }
    return 0;
}
static int DetectTask(void)
{
    while (1) {
        KitReadDetectData(&faceDat);
        sleep(3);
    }
    return 0;
}
void LedTask(void)
{
    while (1) {
        Kit_LED_State(&voicState);
        usleep(100000);
    }
}
//********************************************

static void DeviceConfigInit(hi_gpio_value val)
{
    hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_9, HI_GPIO_DIR_OUT);
    hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val);
}

static int  DeviceMsgCallback(FnMsgCallBack msgCallBack)
{
    g_functionCallback.msgCallBack = msgCallBack;
    return 0;
}

static void wechatControlDeviceMsg(hi_gpio_value val)
{
    DeviceConfigInit(val);
}

// < this is the callback function, set to the mqtt, and if any messages come, it will be called
// < The payload here is the json string
static void DemoMsgRcvCallBack(int qos, const char *topic, const char *payload)
{
    IOT_LOG_DEBUG("RCVMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", qos, topic, payload);
    /* 云端下发命令后，板端的操作处理 */
    if (strstr(payload, WECHAT_SUBSCRIBE_LIGHT) != NULL) {
        if (strstr(payload, WECHAT_SUBSCRIBE_LIGHT_OFF_STATE) != NULL) {
            wechatControlDeviceMsg(HI_GPIO_VALUE1);
            g_ligthStatus = HI_FALSE;
        } else {
            wechatControlDeviceMsg(HI_GPIO_VALUE0);
            g_ligthStatus = HI_TRUE;
        }
    }
    char *timeplace;
    if (strstr(payload, WECHAT_SUBSCRIBE_NOWTIME) != NULL) {
        timeplace = strrchr(payload,'/');
        nowtime.year = (*(timeplace - 7) - '0')*1000 + (*(timeplace - 6) - '0')*100 + (*(timeplace - 5) - '0')*10 +(*(timeplace - 4) - '0')*1;
        nowtime.month = (*(timeplace - 2) - '0')*10 + (*(timeplace - 1) - '0')*1;
        nowtime.day  = (*(timeplace + 1) - '0')*10 + (*(timeplace + 2) - '0')*1;
        nowtime.Hour = (*(timeplace + 4) - '0')*10 + (*(timeplace + 5) - '0')*1;
        nowtime.Min = (*(timeplace + 7) - '0')*10 + (*(timeplace + 8) - '0')*1;
    }
    return HI_NULL;
}

/* publish sample */
hi_void IotPublishDrugs(void)
{
       /* reported attribute */
    WeChatDrugsProfile weChatProfile = {
        .subscribeType = "type",
        .status.subState = "state",
        .status.subReport = "reported",
        .status.reportVersion = "version",
        .status.Token = "clientToken",
    };
    weChatProfile.reportAction.drugid      = "drugid";
    weChatProfile.reportAction.drugname    = "drugname";
    weChatProfile.reportAction.drugNamelen = "drugNamelen";
    weChatProfile.reportAction.drugfill    = "drugfill";
    weChatProfile.reportAction.drugtotal   = "drugtotal";
    weChatProfile.reportAction.drugloc     = "drugloc";
//    for(int i=0;i<Drug_Num_MAX;i++)
//    {    
       int i=0;                     //由于MQTT长度限制及一个便签对应一个数值，先一人一药作为演示读取
       if(DrugData[i].Fill == 1)
       {
        weChatProfile.reportAction.ID         = DrugData[i].ID;     
        strcpy(weChatProfile.reportAction.Name,DrugData[i].Name);              
        weChatProfile.reportAction.NameLen    = DrugData[i].NameLen;         
        weChatProfile.reportAction.Fill       = DrugData[i].Fill;                 
        weChatProfile.reportAction.DrugTotal  = DrugData[i].DrugTotal;       
        weChatProfile.reportAction.Location   = DrugData[i].Location;
         /* profile report */
        IoTProfilePropertyDrugsReport(CONFIG_USER_ID, &weChatProfile);
       }
//    }
}

hi_void IotPublishUsers(void)
{
    int drugidplace;
       /* reported attribute */
    WeChatUsersProfile weChatProfile = {
        .subscribeType = "type",
        .status.subState = "state",
        .status.subReport = "reported",
        .status.reportVersion = "version",
        .status.Token = "clientToken",
    };
    weChatProfile.reportAction.userid		   = "userid"		   ;
    weChatProfile.reportAction.username        = "name"        ;
    weChatProfile.reportAction.userNamelen     = "namelen"     ;
    //weChatProfile.reportAction.userfill        = "userfill"        ;
    weChatProfile.reportAction.userdrugnum     = "drugnum"     ;
    weChatProfile.reportAction.userdrugid     = "drugid"     ;
    weChatProfile.reportAction.userdrugname   = "drugname"   ;
    weChatProfile.reportAction.usertimes      = "times"      ;
    weChatProfile.reportAction.usertimeout    = "timeout"    ;
    weChatProfile.reportAction.userdosagetime = "dosagetime" ;
//    for(int i=0;i<Users_Num_MAX;i++)
//    {    
        int i=2;                                //由于MQTT长度限制及一个便签对应一个数值，先一人一药作为演示读取
       if(UserData[i].Fill == 1)
       {
            weChatProfile.reportAction.ID         = UserData[i].ID;     
            strcpy(weChatProfile.reportAction.Name,UserData[i].Name);              
            weChatProfile.reportAction.NameLen    = UserData[i].NameLen;         
            //weChatProfile.reportAction.Fill       = UserData[i].Fill;                 
            weChatProfile.reportAction.DrugNum    = UserData[i].DrugNum; 
        
        strcpy(weChatProfile.reportAction.DrugName,"NULL"); 
        weChatProfile.reportAction.DrugID=0; 
        weChatProfile.reportAction.Times=0; 
        weChatProfile.reportAction.DosageTime=0; 
        weChatProfile.reportAction.Timeout=0; 
        if(UserData[i].DrugNum != 0)        //演示先以一种药，时间格式161208 代表8点12点16点吃药
         { 
            weChatProfile.reportAction.DrugID=UserData[i].DrugID[0];
            for(int j=0;j<Drug_Num_MAX;j++)
            {
                if(UserData[i].DrugID[0] == DrugData[j].ID)         //查询服药药的ID号
                {
                    drugidplace = j;
                }
            }
            strcpy(weChatProfile.reportAction.DrugName,DrugData[drugidplace].Name); 
            weChatProfile.reportAction.Times=UserData[i].Times[0];
            weChatProfile.reportAction.Timeout=UserData[i].TimeOut[0];
            if(UserData[i].Times[0]==1)
            {    
                weChatProfile.reportAction.DosageTime = UserData[i].DosageTime[0][0];          
            }
            else if(UserData[i].Times[0]==2)
            {    
                weChatProfile.reportAction.DosageTime = UserData[i].DosageTime[0][0];
                weChatProfile.reportAction.DosageTime += UserData[i].DosageTime[0][1] *100;
            }
            else if(UserData[i].Times[0]==3)
            {    
                weChatProfile.reportAction.DosageTime = UserData[i].DosageTime[0][0];
                weChatProfile.reportAction.DosageTime += UserData[i].DosageTime[0][1] *100;
                weChatProfile.reportAction.DosageTime += UserData[i].DosageTime[0][2] *10000;
            }
         }        
         /* profile report */
         sleep(1);
        IoTProfilePropertyUsersReport(CONFIG_USER_ID, &weChatProfile);
      //}
   }
}
hi_void IotPublishLogs(void)
{
    int drugidplace;
       /* reported attribute */
    WeChatLogsProfile weChatProfile = {
        .subscribeType = "type",
        .status.subState = "state",
        .status.subReport = "reported",
        .status.reportVersion = "version",
        .status.Token = "clientToken",
    };
    weChatProfile.reportAction.userid	= "loguserid"		;    //用户ID
    weChatProfile.reportAction.username = "logusername"     ;    //用户名字
    weChatProfile.reportAction.drugname = "logdrugname"     ;    //服用药物
    weChatProfile.reportAction.times    = "logtimes"        ;    //服用要求次数
    weChatProfile.reportAction.num      = "lognum"          ;    //已服药次数
    weChatProfile.reportAction.hour     = "loghour"         ;    //最近服药时间时
    weChatProfile.reportAction.min      = "logmin"          ;    //最近服药时间秒
//    for(int i=0;i<Users_Num_MAX;i++)
//    {    
        int i=0;                                //由于MQTT长度限制 只发送一个日志作为演示
       if(UserData[i].Fill == 1)
       {
            weChatProfile.reportAction.ID         = UserData[i].ID;     
            strcpy(weChatProfile.reportAction.Name,UserData[i].Name); 
            for(int j=0;j<Drug_Num_MAX;j++)
            {
                if(UserData[i].DrugID[0] == DrugData[j].ID)         //查询服药药的ID号
                {
                    drugidplace = j;
                }
            }
            strcpy(weChatProfile.reportAction.DrugName,DrugData[drugidplace].Name);   
            weChatProfile.reportAction.Times    = UserData[i].Times[0];
            weChatProfile.reportAction.Num    = UserLog[i].Num[0]; 
            if(UserLog[i].Hour<10)
            {
                sprintf(weChatProfile.reportAction.Hour,"0%d",UserLog[i].Hour);
            }      
            else
            {
                sprintf(weChatProfile.reportAction.Hour,"%d",UserLog[i].Hour);
            }        
            if(UserLog[i].Min<10)
            {
                sprintf(weChatProfile.reportAction.Min,"0%d",UserLog[i].Min);
            }      
            else
            {
                sprintf(weChatProfile.reportAction.Min,"%d",UserLog[i].Min);
            }            
         /* profile report */
         sleep(1);
        IoTProfilePropertyLogsReport(CONFIG_USER_ID, &weChatProfile);
      //}
   }
}
// < this is the demo main task entry,here we will set the wifi/cjson/mqtt ready and
// < wait if any work to do in the while
static hi_void *DemoEntry(const char *arg)
{
    WifiStaReadyWait();
    cJsonInit();
    IoTMain();
    /* 云端下发回调 */
    IoTSetMsgCallback(DemoMsgRcvCallBack);
    /* 主动上报 */
    while (1) {
        /* 用户可以在这调用发布函数进行发布，需要用户自己写调用函数 */
        IotPublishDrugs(); // 发布药物信息到小程序
        sleep(3);
        IotPublishUsers(); // 发布人物信息到小程序
        sleep(3);
        IotPublishLogs(); // 发布人物信息到小程序
        sleep(3);
        printf("Time:%d/%d/%d %d:%d\n",nowtime.year,nowtime.month,nowtime.day,nowtime.Hour,nowtime.Min);    //打印网络时间
    //    TaskMsleep(ONE_SECOND);
    }
    return NULL;
}

//********************************************
static void KitExampleEntry(void)
{
    osThreadAttr_t attr;
    hi_u32 ret = 0;
    printf("KitTask Strart!\n");
    KitInit();
    attr.name = "KitTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 4096;
    attr.priority = LED_TASK_PRIO;
    if (osThreadNew((osThreadFunc_t)KitTask, NULL, &attr) == NULL) {
        printf("[KitTask] Failed to create KitTask!\n");
    }
    if (osThreadNew((osThreadFunc_t)VoiceTask, NULL, &attr) == NULL) {
        printf("[KitVoiceTask] Failed to create KitTask!\n");
    }
    if (osThreadNew((osThreadFunc_t)DetectTask, NULL, &attr) == NULL) {
        printf("[KitVoiceTask] Failed to create KitTask!\n");
    }
    attr.stack_size = 4096 * 5;
    if (osThreadNew((osThreadFunc_t)DemoEntry, NULL, &attr) == NULL) {
        printf("[mqtt] Failed to create IOTDEMO!\n");
    }

    attr.stack_size = 1024;
    if (osThreadNew((osThreadFunc_t)LedTask, NULL, &attr) == NULL) {
        printf("[KitLedTask] Failed to create KitTask!\n");
    }
}

SYS_RUN(KitExampleEntry);
